from genericpath import isfile
import os
from pydoc import ispath
import re
from typing import Any
from matplotlib import pyplot as plt
from matplotlib import font_manager
from statistics import mean
import numpy as np
fontP = font_manager.FontProperties()
fontP.set_family('simhei')
fontP.set_size(8)



def ToNpArray(list:list) -> np.array:
    result = []
    for item in list:
        if item != 'None':
            result.append(float(item))
        else:
            result.append(0.0)
    return np.array(result)

def To2DNPArray(texts:str) -> np.array:
    result = []
    for text in texts:
        fields = text.split('|')
        numbers = []
        for i, number in enumerate(fields):
            if number != 'None':
                numbers.append(float(number))
            else:
                numbers.append(0.0)
        result.append(numbers)
    return np.array(result)

def ToIntList(list:list) -> list:
    result = []
    for item in list:
        result.append(int(item))
    return result

if __name__ == '__main__':

    path = './statistics'

    for folder_name in os.listdir(path):
        case_path = os.path.join(path, folder_name)
        if ispath(case_path):
            data = dict()
            for file_name in os.listdir(case_path):
                if isfile(os.path.join(case_path, file_name)) and file_name.startswith('测试'):
                    with open(os.path.join(case_path, file_name), encoding='utf-8') as f:
                        content = f.read()
                    name = re.compile(r'测试 ([区分标签头尾整统计数据A-Za-z0-9_\-\.]+).md').findall(file_name)[0]
                    epochs = ToIntList(re.compile(r'测试 \S+ (\d+) 轮').findall(content))
                    losses = ToNpArray(re.compile(r'平均损失 ([\.\d]+)').findall(content))
                    ma_precisions = ToNpArray(re.compile(r'\|PPV Macro\|(\S+)\|\s').findall(content))
                    ma_recalls = ToNpArray(re.compile(r'\|TPR Macro\|(\S+)\|\s').findall(content))
                    ma_f1s = ToNpArray(re.compile(r'\|F1 Macro\|(\S+)\|\s').findall(content))
                    mi_precisions = ToNpArray(re.compile(r'\|PPV Micro\|(\S+)\|\s').findall(content))
                    mi_recalls = ToNpArray(re.compile(r'\|TPR Micro\|(\S+)\|\s').findall(content))
                    mi_f1s = ToNpArray(re.compile(r'\|F1 Micro\|(\S+)\|\s').findall(content))            
                    tags = re.compile(r'\|(O\|\S+)\|\s').search(content).group(1).split('|')
                    num_tags = len(tags)
                    tag_precisions = To2DNPArray(re.compile(r'\|PPV\|(\S+)\|\s').findall(content))
                    tag_recalls = To2DNPArray(re.compile(r'\|TPR\|(\S+)\|\s').findall(content))
                    tag_f1s = To2DNPArray(re.compile(r'\|F1\|(\S+)\|\s').findall(content))
                    data[name] = (epochs, losses, ma_precisions, ma_recalls, ma_f1s, mi_precisions, mi_recalls, mi_f1s, tags, tag_precisions, tag_recalls, tag_f1s)
                    plt.figure(figsize=(6, 4), dpi=300)

                    ma_precision_max = max(ma_precisions)
                    ma_recalls_max = max(ma_recalls)
                    ma_f1_max = max(ma_f1s)
                    print(ma_precision_max, ma_recalls_max, ma_f1_max)

                    mi_precision_max = max(mi_precisions)
                    mi_recalls_max = max(mi_recalls)
                    mi_f1_max = max(mi_f1s)
                    print(mi_precision_max, mi_recalls_max, mi_f1_max)

                    with open(os.path.join(case_path, '关键内容提取_' + name + '.txt'), mode='w', encoding='utf8') as f:
                        num_mean_datapoints = 5
                        name:str = name
                        if 'None' in name:
                            last_epoch = 199
                            num_mean_datapoints = 1
                        elif name.endswith('ccks'):
                            last_epoch = 29
                        elif name.endswith('aiaiyi'):
                            last_epoch = 19
                        else:
                            raise Exception('结尾不正确')
                        selector = slice(last_epoch - num_mean_datapoints, last_epoch + 1)
                        mean_ma_precision = np.mean(ma_precisions[selector])
                        mean_ma_recall = np.mean(ma_recalls[selector])
                        mean_f1 = np.mean(ma_f1s[selector])
                        mean_tag_precisions = np.mean(tag_precisions[selector], 0)
                        mean_tag_recalls = np.mean(tag_recalls[selector], 0)
                        mean_tag_f1s = np.mean(tag_f1s[selector], 0)
                        f.write(f'{"Macro Precision":<20} {mean_ma_precision:>20}\n')
                        f.write(f'{"Macro Recall":<20} {mean_ma_recall:>20}\n')
                        f.write(f'{"Macro F1":<20} {mean_f1:>20}\n')
                        f.write(f'\n')
                        f.write(f'{"Tag":<20}{"Precision":>20}{"Recall":>20}{"F1":>20}\n')
                        for itag, (tag_precision, tag_recall, tag_f1) in enumerate(zip(mean_tag_precisions, mean_tag_recalls, mean_tag_f1s)):
                            f.write(f'{tags[itag]:<20}{tag_precision:>20}{tag_recall:>20}{tag_f1:>20}\n')

                    description = name + ' Macro Precision, Recall and F1'
                    plt.title(description)
                    plt.xlabel('epochs')
                    plt.ylabel('Macro Precision, Recall and F1')
                    plt.plot(epochs, ma_precisions, label='Macro Precision')
                    plt.plot(epochs, ma_recalls, label='Macro Recall')
                    plt.plot(epochs, ma_f1s, label='Macro F1')
                    plt.legend(prop=fontP)
                    plt.savefig(os.path.join(case_path, description + '.svg'))
                    plt.clf()
                    plt.cla()

                    description = name + ' Micro Precision, Recall and F1'
                    plt.title(description)
                    plt.xlabel('epochs')
                    plt.ylabel('Micro Precision, Recall and F1')
                    plt.plot(epochs, ma_precisions, label='Micro Precision')
                    plt.plot(epochs, ma_recalls, label='Micro Recall')
                    plt.plot(epochs, ma_f1s, label='Micro F1')
                    plt.legend(prop=fontP)
                    plt.savefig(os.path.join(case_path, description + '.svg'))
                    plt.clf()
                    plt.cla()

                    description = name + ' Per-Tag Precision'
                    plt.title(description)
                    plt.xlabel('epochs')
                    plt.ylabel('Per-Tag Precision')
                    plt.plot(epochs, tag_precisions, label=tags)
                    plt.legend(prop=fontP)
                    plt.savefig(os.path.join(case_path, description + '.svg'))
                    plt.clf()
                    plt.cla()

                    description = name + ' Per-Tag Recall'
                    plt.title(description)
                    plt.xlabel('epochs')
                    plt.ylabel('Per-Tag Recall')
                    plt.plot(epochs, tag_recalls, label=tags)
                    plt.legend(prop=fontP)
                    plt.savefig(os.path.join(case_path, description + '.svg'))
                    plt.clf()
                    plt.cla()

                    description = name + ' Per-Tag F1'
                    plt.title(description)
                    plt.xlabel('epochs')
                    plt.ylabel('Per-Tag F1')
                    plt.plot(epochs, tag_f1s, label=tags)
                    plt.legend(prop=fontP)
                    plt.savefig(os.path.join(case_path, description + '.svg'))
                    plt.clf()
                    plt.cla()

                    description = name + ' Loss'
                    plt.title(description)
                    plt.xlabel('epochs')
                    plt.ylabel('Loss')
                    plt.plot(epochs, losses)
                    plt.legend(prop=fontP)
                    plt.savefig(os.path.join(case_path, description + '.svg'))
                    plt.clf()
                    plt.cla()